/*   1:    */ package org.intellij.lang.regexp.validation;
/*   2:    */ 
/*   3:    */

import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.lang.ASTNode;
import com.intellij.lang.annotation.Annotation;
import com.intellij.lang.annotation.AnnotationHolder;
import com.intellij.lang.annotation.Annotator;
import com.intellij.psi.PsiComment;
import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil;
import org.intellij.lang.regexp.RegExpLanguageHosts;
import org.intellij.lang.regexp.RegExpTT;
import org.intellij.lang.regexp.psi.*;
import org.jetbrains.annotations.NotNull;

import java.math.BigInteger;

/*   4:    */
/*   5:    */
/*   6:    */
/*   7:    */
/*   8:    */
/*   9:    */
/*  10:    */
/*  11:    */
/*  12:    */
/*  13:    */
/*  14:    */
/*  15:    */
/*  16:    */
/*  17:    */
/*  18:    */
/*  19:    */
/*  20:    */
/*  21:    */
/*  22:    */
/*  23:    */
/*  24:    */
/*  25:    */
/*  26:    */
/*  27:    */
/*  28:    */
/*  29:    */
/*  30:    */
/*  31:    */
/*  32:    */ 
/*  33:    */ public final class RegExpAnnotator
/*  34:    */   extends RegExpElementVisitor
/*  35:    */   implements Annotator
/*  36:    */ {
/*  37:    */   private AnnotationHolder a;
/*  38:    */   private final RegExpLanguageHosts b;
/*  39:    */   
/*  40:    */   public RegExpAnnotator()
/*  41:    */   {
/*  42: 38 */     this.b = RegExpLanguageHosts.getInstance();
/*  43:    */   }
/*  44:    */   
/*  45:    */   public void annotate(@NotNull PsiElement paramPsiElement, @NotNull AnnotationHolder paramAnnotationHolder)
/*  46:    */   {
/*  47: 42 */     if (paramPsiElement == null) {
/*  48: 42 */       throw new IllegalArgumentException(String.format("Argument %s for @NotNull parameter of %s.%s must not be null", new Object[] { "0", "org/intellij/lang/regexp/validation/RegExpAnnotator", "annotate" }));
/*  49:    */     }
/*  50: 42 */     if (paramAnnotationHolder == null) {
/*  51: 42 */       throw new IllegalArgumentException(String.format("Argument %s for @NotNull parameter of %s.%s must not be null", new Object[] { "1", "org/intellij/lang/regexp/validation/RegExpAnnotator", "annotate" }));
/*  52:    */     }
/*  53: 42 */     assert (this.a == null) : "unsupported concurrent annotator invocation";
/*  54:    */     try
/*  55:    */     {
/*  56: 44 */       this.a = paramAnnotationHolder;
/*  57: 45 */       paramPsiElement.accept(this);
/*  58:    */     }
/*  59:    */     finally
/*  60:    */     {
/*  61: 48 */       this.a = null;
/*  62:    */     }
/*  63:    */   }
/*  64:    */   
/*  65:    */   public void visitRegExpCharRange(RegExpCharRange paramRegExpCharRange)
/*  66:    */   {
/*  67: 53 */     RegExpCharRange.Endpoint localEndpoint1 = paramRegExpCharRange.getFrom();
/*  68: 54 */     RegExpCharRange.Endpoint localEndpoint2 = paramRegExpCharRange.getTo();
/*  69: 55 */     boolean bool1 = localEndpoint1 instanceof RegExpChar;
/*  70: 56 */     boolean bool2 = localEndpoint2 instanceof RegExpChar;
/*  71: 57 */     if ((bool1) && (bool2))
/*  72:    */     {
/*  73: 58 */       Character localCharacter1 = ((RegExpChar)localEndpoint2).getValue();
/*  74: 59 */       Character localCharacter2 = ((RegExpChar)localEndpoint1).getValue();
/*  75: 60 */       if ((localCharacter1 != null) && (localCharacter2 != null)) {
/*  76: 61 */         if (localCharacter1.charValue() < localCharacter2.charValue()) {
/*  77: 62 */           this.a.createErrorAnnotation(paramRegExpCharRange, "Illegal character range (to < from)");
/*  78: 64 */         } else if (localCharacter1 == localCharacter2) {
/*  79: 65 */           this.a.createWarningAnnotation(paramRegExpCharRange, "Redundant character range");
/*  80:    */         }
/*  81:    */       }
/*  82:    */     }
/*  83: 69 */     else if (bool1 != bool2)
/*  84:    */     {
/*  85: 70 */       this.a.createErrorAnnotation(paramRegExpCharRange, "Character class (e.g. '\\\\w') may not be used inside character range");
/*  86:    */     }
/*  87: 72 */     else if (localEndpoint1.getText().equals(localEndpoint2.getText()))
/*  88:    */     {
/*  89: 73 */       this.a.createWarningAnnotation(paramRegExpCharRange, "Redundant character range");
/*  90:    */     }
/*  91:    */   }
/*  92:    */   
/*  93:    */   public void visitRegExpChar(RegExpChar paramRegExpChar)
/*  94:    */   {
/*  95: 78 */     Character localCharacter = paramRegExpChar.getValue();
/*  96: 79 */     if (localCharacter == null)
/*  97:    */     {
/*  98: 80 */       switch (1.$SwitchMap$org$intellij$lang$regexp$psi$RegExpChar$Type[paramRegExpChar.getType().ordinal()])
/*  99:    */       {
/* 100:    */       case 1: 
/* 101: 82 */         this.a.createErrorAnnotation(paramRegExpChar, "Illegal/unsupported escape sequence");
/* 102: 83 */         break;
/* 103:    */       case 2: 
/* 104: 85 */         this.a.createErrorAnnotation(paramRegExpChar, "Illegal hexadecimal escape sequence");
/* 105: 86 */         break;
/* 106:    */       case 3: 
/* 107: 88 */         this.a.createErrorAnnotation(paramRegExpChar, "Illegal octal escape sequence");
/* 108: 89 */         break;
/* 109:    */       case 4: 
/* 110: 91 */         this.a.createErrorAnnotation(paramRegExpChar, "Illegal unicode escape sequence");
/* 111: 92 */         break;
/* 112:    */       }
/* 113:    */     }
/* 114:    */     else
/* 115:    */     {
/* 116: 99 */       String str = paramRegExpChar.getUnescapedText();
/* 117:100 */       if ((str.startsWith("\\")) && (this.b.isRedundantEscape(paramRegExpChar, str)))
/* 118:    */       {
/* 119:101 */         ASTNode localASTNode = paramRegExpChar.getNode().getFirstChildNode();
/* 120:102 */         if ((localASTNode != null) && (localASTNode.getElementType() == RegExpTT.REDUNDANT_ESCAPE))
/* 121:    */         {
/* 122:103 */           Annotation localAnnotation = this.a.createWeakWarningAnnotation(paramRegExpChar, "Redundant character escape");
/* 123:104 */           a(localAnnotation, new RemoveRedundantEscapeAction(paramRegExpChar));
/* 124:    */         }
/* 125:    */       }
/* 126:    */     }
/* 127:    */   }
/* 128:    */   
/* 129:    */   public void visitRegExpProperty(RegExpProperty paramRegExpProperty)
/* 130:    */   {
/* 131:111 */     ASTNode localASTNode = paramRegExpProperty.getCategoryNode();
/* 132:112 */     if (localASTNode == null) {
/* 133:113 */       return;
/* 134:    */     }
/* 135:115 */     if (!this.b.isValidCategory(localASTNode.getPsi(), localASTNode.getText()))
/* 136:    */     {
/* 137:116 */       Annotation localAnnotation = this.a.createErrorAnnotation(localASTNode, "Unknown character category");
/* 138:117 */       if (localAnnotation != null) {
/* 139:119 */         localAnnotation.setHighlightType(ProblemHighlightType.LIKE_UNKNOWN_SYMBOL);
/* 140:    */       }
/* 141:    */     }
/* 142:    */   }
/* 143:    */   
/* 144:    */   public void visitRegExpBackref(RegExpBackref paramRegExpBackref)
/* 145:    */   {
/* 146:125 */     RegExpGroup localRegExpGroup = paramRegExpBackref.resolve();
/* 147:126 */     if (localRegExpGroup == null)
/* 148:    */     {
/* 149:127 */       Annotation localAnnotation = this.a.createErrorAnnotation(paramRegExpBackref, "Unresolved backreference");
/* 150:128 */       if (localAnnotation != null) {
/* 151:130 */         localAnnotation.setHighlightType(ProblemHighlightType.LIKE_UNKNOWN_SYMBOL);
/* 152:    */       }
/* 153:    */     }
/* 154:133 */     else if (PsiTreeUtil.isAncestor(localRegExpGroup, paramRegExpBackref, true))
/* 155:    */     {
/* 156:134 */       this.a.createWarningAnnotation(paramRegExpBackref, "Backreference is nested into the capturing group it refers to");
/* 157:    */     }
/* 158:    */   }
/* 159:    */   
/* 160:    */   public void visitRegExpGroup(RegExpGroup paramRegExpGroup)
/* 161:    */   {
/* 162:139 */     RegExpPattern localRegExpPattern = paramRegExpGroup.getPattern();
/* 163:140 */     if (localRegExpPattern != null)
/* 164:    */     {
/* 165:141 */       RegExpBranch[] arrayOfRegExpBranch = localRegExpPattern.getBranches();
/* 166:142 */       if (a(arrayOfRegExpBranch))
/* 167:    */       {
/* 168:144 */         this.a.createWarningAnnotation(paramRegExpGroup, "Empty group");
/* 169:    */       }
/* 170:146 */       else if (arrayOfRegExpBranch.length == 1)
/* 171:    */       {
/* 172:147 */         RegExpAtom[] arrayOfRegExpAtom = arrayOfRegExpBranch[0].getAtoms();
/* 173:148 */         if ((arrayOfRegExpAtom.length == 1) && ((arrayOfRegExpAtom[0] instanceof RegExpGroup)) && 
/* 174:149 */           (paramRegExpGroup.isSimple()))
/* 175:    */         {
/* 176:150 */           RegExpGroup localRegExpGroup = (RegExpGroup)arrayOfRegExpAtom[0];
/* 177:151 */           if (paramRegExpGroup.isCapturing() == localRegExpGroup.isCapturing()) {
/* 178:152 */             this.a.createWarningAnnotation(paramRegExpGroup, "Redundant group nesting");
/* 179:    */           }
/* 180:    */         }
/* 181:    */       }
/* 182:    */     }
/* 183:158 */     if (((paramRegExpGroup.isPythonNamedGroup()) || (paramRegExpGroup.isRubyNamedGroup())) && 
/* 184:159 */       (!this.b.supportsNamedGroupSyntax(paramRegExpGroup))) {
/* 185:160 */       this.a.createErrorAnnotation(paramRegExpGroup, "This named group syntax is not supported");
/* 186:    */     }
/* 187:    */   }
/* 188:    */   
/* 189:    */   public void visitRegExpPyNamedGroupRef(RegExpPyNamedGroupRef paramRegExpPyNamedGroupRef)
/* 190:    */   {
/* 191:174 */     RegExpGroup localRegExpGroup = paramRegExpPyNamedGroupRef.resolve();
/* 192:175 */     if (localRegExpGroup == null)
/* 193:    */     {
/* 194:176 */       Annotation localAnnotation = this.a.createErrorAnnotation(paramRegExpPyNamedGroupRef, "Unresolved backreference");
/* 195:177 */       if (localAnnotation != null) {
/* 196:179 */         localAnnotation.setHighlightType(ProblemHighlightType.LIKE_UNKNOWN_SYMBOL);
/* 197:    */       }
/* 198:    */     }
/* 199:182 */     else if (PsiTreeUtil.isAncestor(localRegExpGroup, paramRegExpPyNamedGroupRef, true))
/* 200:    */     {
/* 201:183 */       this.a.createWarningAnnotation(paramRegExpPyNamedGroupRef, "Group reference is nested into the named group it refers to");
/* 202:    */     }
/* 203:    */   }
/* 204:    */   
/* 205:    */   public void visitComment(PsiComment paramPsiComment)
/* 206:    */   {
/* 207:189 */     if ((paramPsiComment.getText().startsWith("(?#")) && 
/* 208:190 */       (!this.b.supportsPerl5EmbeddedComments(paramPsiComment))) {
/* 209:191 */       this.a.createErrorAnnotation(paramPsiComment, "Embedded comments are not supported");
/* 210:    */     }
/* 211:    */   }
/* 212:    */   
/* 213:    */   public void visitRegExpPyCondRef(RegExpPyCondRef paramRegExpPyCondRef)
/* 214:    */   {
/* 215:198 */     if (!this.b.supportsPythonConditionalRefs(paramRegExpPyCondRef)) {
/* 216:199 */       this.a.createErrorAnnotation(paramRegExpPyCondRef, "Conditional references are not supported");
/* 217:    */     }
/* 218:    */   }
/* 219:    */   
/* 220:    */   private static boolean a(RegExpBranch[] paramArrayOfRegExpBranch)
/* 221:    */   {
/* 222:204 */     for (RegExpBranch localRegExpBranch : paramArrayOfRegExpBranch) {
/* 223:205 */       if (localRegExpBranch.getAtoms().length > 0) {
/* 224:206 */         return false;
/* 225:    */       }
/* 226:    */     }
/* 227:209 */     return true;
/* 228:    */   }
/* 229:    */   
/* 230:    */   public void visitRegExpQuantifier(RegExpQuantifier paramRegExpQuantifier)
/* 231:    */   {
/* 232:213 */     RegExpQuantifier.Count localCount = paramRegExpQuantifier.getCount();
/* 233:214 */     if (!(localCount instanceof RegExpQuantifier.SimpleCount))
/* 234:    */     {
/* 235:215 */       String str1 = localCount.getMin();
/* 236:216 */       String str2 = localCount.getMax();
/* 237:    */       Object localObject1;
/* 238:    */       Object localObject2;
/* 239:217 */       if (str2.equals(str1))
/* 240:    */       {
/* 241:218 */         if ("1".equals(str2))
/* 242:    */         {
/* 243:219 */           localObject1 = this.a.createWeakWarningAnnotation(paramRegExpQuantifier, "Single repetition");
/* 244:220 */           a((Annotation)localObject1, new SimplifyQuantifierAction(paramRegExpQuantifier, null));
/* 245:    */         }
/* 246:    */         else
/* 247:    */         {
/* 248:223 */           localObject1 = paramRegExpQuantifier.getNode();
/* 249:224 */           if (((ASTNode)localObject1).findChildByType(RegExpTT.COMMA) != null)
/* 250:    */           {
/* 251:225 */             localObject2 = this.a.createWeakWarningAnnotation(paramRegExpQuantifier, "Fixed repetition range");
/* 252:226 */             a((Annotation)localObject2, new SimplifyQuantifierAction(paramRegExpQuantifier, "{" + str2 + "}"));
/* 253:    */           }
/* 254:    */         }
/* 255:    */       }
/* 256:230 */       else if (("0".equals(str1)) && ("1".equals(str2)))
/* 257:    */       {
/* 258:231 */         localObject1 = this.a.createWeakWarningAnnotation(paramRegExpQuantifier, "Repetition range replaceable by '?'");
/* 259:232 */         a((Annotation)localObject1, new SimplifyQuantifierAction(paramRegExpQuantifier, "?"));
/* 260:    */       }
/* 261:234 */       else if (("0".equals(str1)) && (str2.isEmpty()))
/* 262:    */       {
/* 263:235 */         localObject1 = this.a.createWeakWarningAnnotation(paramRegExpQuantifier, "Repetition range replaceable by '*'");
/* 264:236 */         a((Annotation)localObject1, new SimplifyQuantifierAction(paramRegExpQuantifier, "*"));
/* 265:    */       }
/* 266:238 */       else if (("1".equals(str1)) && (str2.isEmpty()))
/* 267:    */       {
/* 268:239 */         localObject1 = this.a.createWeakWarningAnnotation(paramRegExpQuantifier, "Repetition range replaceable by '+'");
/* 269:240 */         a((Annotation)localObject1, new SimplifyQuantifierAction(paramRegExpQuantifier, "+"));
/* 270:    */       }
/* 271:242 */       else if ((!str1.isEmpty()) && (!str2.isEmpty()))
/* 272:    */       {
/* 273:    */         try
/* 274:    */         {
/* 275:244 */           localObject1 = new BigInteger(str1);
/* 276:245 */           localObject2 = new BigInteger(str2);
/* 277:246 */           if (((BigInteger)localObject2).compareTo((BigInteger)localObject1) < 0) {
/* 278:247 */             this.a.createErrorAnnotation(paramRegExpQuantifier, "Illegal repetition range");
/* 279:    */           }
/* 280:    */         }
/* 281:    */         catch (NumberFormatException localNumberFormatException)
/* 282:    */         {
/* 283:251 */           this.a.createErrorAnnotation(paramRegExpQuantifier, "Illegal repetition value");
/* 284:    */         }
/* 285:    */       }
/* 286:    */     }
/* 287:255 */     if ((paramRegExpQuantifier.getType() == RegExpQuantifier.Type.POSSESSIVE) && 
/* 288:256 */       (!this.b.supportsPossessiveQuantifiers(paramRegExpQuantifier))) {
/* 289:257 */       this.a.createErrorAnnotation(paramRegExpQuantifier, "Nested quantifier in regexp");
/* 290:    */     }
/* 291:    */   }
/* 292:    */   
/* 293:    */   private static void a(Annotation paramAnnotation, IntentionAction paramIntentionAction)
/* 294:    */   {
/* 295:263 */     if (paramAnnotation != null) {
/* 296:265 */       paramAnnotation.registerFix(paramIntentionAction);
/* 297:    */     }
/* 298:    */   }
/* 299:    */ }



/* Location:           E:\idea\

 * Qualified Name:     org.intellij.lang.regexp.validation.RegExpAnnotator

 * JD-Core Version:    0.7.0.1

 */